/*
  File: T.cls
  
  Description:
  
  Apex test setup & utility functions.
  
  Author: 
  
  John Hart
  
  Copyright: 
  
  Copyright 2010, iHance, Inc.
  
  Homepage: 
  
  <http://www.ihance.com>
  
  Version: 
  
  1.3.0

  License: GPLv3

 */
public abstract class T {
	public static final string dmn = 'chat.test.' + rand() + '.example.com'; // random email domain to use in tests

	public static User u1, u2, u3;				// 3 new users
	public static Account a1, a2;
	public static Opportunity o1, o2;			// c1 = o1, c2 = o1 + o2
	public static Lead l1, l2, l3;				// 3 leads; l3 is converted into c3
	public static Contact c1, c2, c3; 		// 3 contacts: c1/c2 in a1, c3 in a2 (and converted from l3)
	public static Case case1, case2;			// 2 cases (1 open, 1 closed)


	private static boolean setupDone = false;
	public static void setup() { if (!isTestOrg()) return;
		if (setupDone) return;
		createTestUsers();		
		createTestLeads();	
		createTestContacts(); // and accounts & ops
		createTestCases();
		setupDone = true;	
		}


	// used to restrict test execution to the DE org if necessary
	public static boolean isTestOrg() {
		return true; //UserInfo.getOrganizationId() == '00DA0000000YQDhMAO';
		}

	// typing 'System.assert...' gets old
	public static void ok(boolean test)                             { System.assert(test); }
	public static void ok(boolean test, string name)                { System.assert(test, name); }
	public static void is(object want, object got)                  { System.assertEquals(want,got); }
	public static void is(object want, object got, string name)     { System.assertEquals(want,got,name); }
	public static void is(object[] want, object[] got)              { System.assertEquals(want,got); }
	public static void is(object[] want, object[] got, string name) { System.assertEquals(want,got,name); }

		
	private static string lastRand = null;
	private static string rand() {
		return lastRand = String.valueOf(System.now().getTime()/1000)
			+ '.' + String.valueOf(Limits.getScriptStatements())
			+ '.' + Math.rint(Math.random() * 100000);
		}

	//-------------------------------------------------------------------------------
	// privates - user/contact/lead setup etc
	//-------------------------------------------------------------------------------

	private static User sysAdmin = null;
	private static User getSysAdmin() {
		if (sysAdmin == null) sysAdmin = [select Id from User where ProfileId in (select Id from Profile where Name = 'System Administrator') limit 1][0];
		return sysAdmin;
		}

	private static User stdUser = null;
	private static User getStdUser() { // we query all required fields so inserting clones works
		if (stdUser == null) stdUser = [select Username, Alias, Email, CommunityNickname, TimeZoneSidKey, LocaleSidKey, EmailEncodingKey, ProfileId, LanguageLocaleKey from User where ProfileId in (select Id from Profile where Name = 'Standard User') limit 1][0];
		return stdUser;
		}

	
	private static void createTestUsers() {
		System.runAs(getSysAdmin()) {
			insert new User[] { u1 = genTestUser(1), u2 = genTestUser(2), u3 = genTestUser(3) };
			}
		}

	private static User genTestUser(integer i) {
		User template = [select TimeZoneSidKey, LocaleSidKey, EmailEncodingKey, LanguageLocaleKey from User where Id = :UserInfo.getUserId()];
		return new User(
			Username = 'sys.admin+chat.testuser.' + i + '@ihance.com',
			Email =  'sys.admin+chat.testuser.' + i + '@ihance.com',
			CommunityNickName = 'test' + i,
			Alias = 'test' + i,
			FirstName = 'TestUser',
			LastName = 'Number' + i,
			TimeZoneSidKey    = template.TimeZoneSidKey,
			LocaleSidKey      = template.LocaleSidKey,
			EmailEncodingKey  = template.EmailEncodingKey,
			LanguageLocaleKey = template.LanguageLocaleKey,
			ProfileId = [select Id from Profile where Name = 'Standard User' limit 1][0].Id
			);
		}

	
	private static void createTestContacts() {
		insert new Account[] {
			 a1 = new Account(Name = 'Test Account 1.' + dmn)
			,a2 = new Account(Name = 'Test Account 2.' + dmn)
			};
		insert new Contact[] {
			 c1 = new Contact(AccountId = a1.Id, FirstName = 'Test', LastName = 'Contact1', Email = 'test.contact1@1.' + dmn)
			,c2 = new Contact(AccountId = a1.Id, FirstName = 'Test', LastName = 'Contact2', Email = 'test.contact2@1.' + dmn)
			,c3 = new Contact(AccountId = a2.Id, FirstName = 'Test', LastName = 'Contact3', Email = 'test.contact3@2.' + dmn)
			};

		insert new Opportunity[] {
			 o1 = new Opportunity(AccountId = a1.Id, Name = 'Test Opportunity 1.' + dmn, StageName = 'Prospecting', CloseDate = System.today().addMonths(1))
			,o2 = new Opportunity(AccountId = a1.Id, Name = 'Test Opportunity 2.' + dmn, StageName = 'Prospecting', CloseDate = System.today().addMonths(1))
			};
		insert new OpportunityContactRole[] {
			 new OpportunityContactRole(OpportunityId = o1.Id, ContactId = c1.Id, Role = 'Business User')
			,new OpportunityContactRole(OpportunityId = o2.Id, ContactId = c1.Id, Role = 'Business User')
			,new OpportunityContactRole(OpportunityId = o2.Id, ContactId = c2.Id, Role = 'Business User')
			};


		Database.LeadConvert lc = new database.LeadConvert();
		lc.setLeadId(l3.Id);
		lc.setContactId(c3.Id);
		lc.setAccountId(c3.AccountId);
		lc.setConvertedStatus([Select Id, MasterLabel from LeadStatus where IsConverted=true limit 1].MasterLabel);
		Database.LeadConvertResult lcr = Database.convertLead(lc);
		
		l3 = [select Company, FirstName, LastName, Email, IsConverted from Lead where Id = :l3.Id];
		}

	private static void createTestLeads() {
		insert new Lead[] {
			 l1 = new Lead(Company = 'Test', FirstName = 'Test', LastName = 'Lead1', Email = 'test.lead1@1.' + dmn)
			,l2 = new Lead(Company = 'Test', FirstName = 'Test', LastName = 'Lead2', Email = 'test.lead2@1.' + dmn)
			,l3 = new Lead(Company = 'Test', FirstName = 'Test', LastName = 'Lead3', Email = 'test.contact3@2.' + dmn)
			};
		}

	private static void createTestCases() {
		insert new Case[] {
			 case1 = new Case(Status = 'Open',   Origin = 'Email', Subject = 'case 1.' + dmn, Description = 'test case (open)')
			,case2 = new Case(Status = 'Closed', Origin = 'Email', Subject = 'case 2.' + dmn, Description = 'test case (closed)')
			};
		}



	//-------------------------------------------------------------------------------
	// test post insertion - not part of setup(), must be called afterward
	//-------------------------------------------------------------------------------
	public static void insertTestPosts() {
		System.runAs(T.u1) {
			insert genPosts(new Map<Id, integer> {
				 c1.Id => 2
				,c2.Id => 6
				,l1.Id => 3
				,l2.Id => 4
				});
			}
		System.runAs(T.u2) {
			insert genPosts(new Map<Id, integer> {
				 c2.Id => 3
				,c3.Id => 15
				,l2.Id => 8
				});
			}
		}

	private static FeedPost[] genPosts(Map<Id, integer> pMap) {
		FeedPost[] ret = new FeedPost[0];
		for (Id k : pMap.keySet()) for (integer i=pMap.get(k); i>0; i--) ret.add(genPost(k));
		return ret;
		}

	private static FeedPost genPost(Id parentId) {
		return new FeedPost(
			 ParentId = parentId
			,Type = 'TextPost'
			,Body = 'test post for chatter graphs'
			);
		}

	//-------------------------------------------------------------------------------
	// tests
	//-------------------------------------------------------------------------------
	private static testMethod void testSetup() {
		T.setup();
		ok(l3.IsConverted);
		
		T.insertTestPosts();
		is( 2, [select count() from ContactFeed where CreatedById = :u1.Id and ParentId = :c1.Id]);
		is(15, [select count() from ContactFeed where CreatedById = :u2.Id and ParentId = :c3.Id]);
		is( 3, [select count() from LeadFeed    where CreatedById = :u1.Id and ParentId = :l1.Id]);
		is( 8, [select count() from LeadFeed    where CreatedById = :u2.Id and ParentId = :l2.Id]);
		}
	
	
	
	}
